home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / dvips / drawPS.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-06  |  10.7 KB  |  400 lines

  1. /*
  2.  *                      D R A W P S . C 
  3.  * (minor mods by don on 5 Jan 90 to accommodate highres PostScript)
  4.  *
  5.  * $Revision: 1.4 $
  6.  *
  7.  * $Log:        drawPS.c,v $
  8.  *
  9.  * 89/04/24: decouty@irisa.fr, priol@irisa.fr
  10.  *              added three shading levels for fig,
  11.  *              removed '\n' in cmdout() calls
  12.  *
  13.  * Revision 1.4  87/05/07  15:06:24  dorab
  14.  * relinked back hh to h and vv to v undoing a previous change.
  15.  * this was causing subtle quantization problems. the main change
  16.  * is in the definition of hconvPS and vconvPS.
  17.  * 
  18.  * changed the handling of the UC seal. the PS file should now be
  19.  * sent via the -i option.
  20.  * 
  21.  * Revision 1.3  86/04/29  23:20:55  dorab
  22.  * first general release
  23.  * 
  24.  * Revision 1.3  86/04/29  22:59:21  dorab
  25.  * first general release
  26.  * 
  27.  * Revision 1.2  86/04/29  13:23:40  dorab
  28.  * Added distinctive RCS header
  29.  * 
  30.  */
  31. #ifndef lint
  32. static char RCSid[] = 
  33.   "@(#)$Header: drawPS.c,v 1.4 87/05/07 15:06:24 dorab Exp $ (UCLA)";
  34. #endif
  35.  
  36. /*
  37.  the driver for handling the \special commands put out by
  38.  the tpic program as modified by Tim Morgan <morgan@uci.edu>
  39.  the co-ordinate system is with the origin at the top left
  40.  and the x-axis is to the right, and the y-axis is to the bottom.
  41.  when these routines are called, the origin is set at the last dvi position,
  42.  which has to be gotten from the dvi-driver (in this case, dvips) and will
  43.  have to be converted to device co-ordinates (in this case, by [hv]convPS).
  44.  all dimensions are given in milli-inches and must be converted to what
  45.  dvips has set up (i.e. there are convRESOLUTION units per inch).
  46.  
  47.  it handles the following \special commands
  48.     pn n                        set pen size to n
  49.     pa x y                      add path segment to (x,y)
  50.     fp                          flush path
  51.     da l                        flush dashed - each dash is l (inches)
  52.     dt l                        flush dotted - one dot per l (inches)
  53.     sp                          flush spline
  54.     ar x y xr yr sa ea          arc centered at (x,y) with x-radius xr
  55.                                 and y-radius yr, start angle sa (in rads),
  56.                                 end angle ea (in rads)
  57.     sh                          shade last path (box, circle, ellipse)
  58.     wh                          whiten last path (box, circle, ellipse)
  59.     bk                          blacken last path (box,circle, ellipse)
  60.     tx                          texture command - Added by T. Priol (priol@irisa.fr)
  61.  
  62.   this code is in the public domain
  63.  
  64.   written by dorab patel <dorab@cs.ucla.edu>
  65.   december 1985
  66.   released feb 1986
  67.   changes for dvips july 1987
  68.  
  69.   */
  70.  
  71. #ifdef TPIC                     /* rest of the file !! */
  72.  
  73. #include "structures.h"
  74.  
  75. #ifdef DEBUG
  76. extern integer debug_flag;
  77. #endif  /* DEBUG */
  78.  
  79.  
  80. /*
  81.  * external functions used here
  82.  */
  83. extern void cmdout();
  84. extern void numout();
  85. extern void error();
  86.  
  87. /*
  88.  * external variables used here
  89.  */
  90. extern integer hh,vv;           /* the current x,y position in pixel units */
  91. extern int actualdpi ;
  92.  
  93. #define convRESOLUTION DPI
  94. #define TRUE 1
  95. #define FALSE 0
  96. #define tpicRESOLUTION 1000     /* number of tpic units per inch */
  97.  
  98. /* convert from tpic units to PS units */
  99. #define PixRound(a,b) zPixRound((integer)(a),(integer)(b))
  100. #define convPS(x) PixRound((x)*convRESOLUTION,tpicRESOLUTION)
  101.  
  102. /* convert from tpic locn to abs horiz PS locn */
  103. #define hconvPS(x) (integer)(hh + convPS(x))
  104. /* convert from tpic locn to abs vert PS locn */
  105. #define vconvPS(x) (integer)(vv + convPS(x))
  106. #define convDeg(x) (integer)(360*(x)/(2*3.14159265358)+0.5) /* convert to degs */
  107.  
  108. /* if PostScript had splines, i wouldnt need to store the path */
  109. #define MAXPATHS 300            /* maximum number of path segments */
  110. #define NONE 0                  /* for shading */
  111. #define BLACK           1       /* for shading */
  112. #define DARK_GRAY       2       /* for shading */
  113. #define MEDIUM_GRAY     3       /* for shading */
  114. #define LIGHT_GRAY      4       /* for shading */
  115. #define WHITE           5       /* for shading */
  116.  
  117. /* the following defines are used to make the PostScript shorter;
  118.   the corresponding defines are in the PostScript prolog special.lpro */
  119. #define MOVETO "a"
  120. #define LINETO "li"
  121. #define RCURVETO "rc"
  122. #define RLINETO "rl"
  123. #define STROKE "st"
  124. #define FILL "fil"
  125. #define NEWPATH "np"
  126. #define CLOSEPATH "closepath"
  127. /*
  128.  * STROKE and FILL must restore the current point to that
  129.  * saved by NEWPATH
  130.  */
  131.  
  132. static integer xx[MAXPATHS], yy[MAXPATHS]; /* the current path in milli-inches */
  133. static integer pathLen = 0;             /* the current path length */
  134. static integer shading = NONE;  /* what to shade the last figure */
  135. static integer penSize = 2;             /* pen size in PS units */
  136.  
  137. /* forward declarations */
  138. static void doShading();
  139. static integer zPixRound();             /* (int)(x/y)PixRound((int)x,(int)y) */
  140. static double  shadetp;                 /* shading level        */
  141.  
  142. void
  143. setPenSize(cp)
  144.      char *cp;
  145. {
  146.   long ps;
  147.  
  148.   if (sscanf(cp, " %ld ", &ps) != 1) 
  149.     {
  150.       error("Illegal .ps command format");
  151.       return;
  152.     }
  153.  
  154.   penSize = convPS(ps);
  155.   numout((integer)penSize);
  156.   cmdout("setlinewidth");
  157. }                               /* end setPenSize */
  158.  
  159. void
  160. addPath(cp)
  161.      char *cp;
  162. {
  163.   long x,y;
  164.  
  165.   if (++pathLen >= MAXPATHS) error("! Too many points");
  166.   if (sscanf(cp, " %ld %ld ", &x, &y) != 2)
  167.     error("! Malformed path expression");
  168.   xx[pathLen] = x;
  169.   yy[pathLen] = y;
  170. }                               /* end of addPath */
  171.  
  172. void
  173. arc(cp)
  174.      char *cp;
  175. {
  176.   long xc, yc, xrad, yrad;
  177.   float startAngle, endAngle;
  178.  
  179.   if (sscanf(cp, " %ld %ld %ld %ld %f %f ", &xc, &yc, &xrad, &yrad,
  180.              &startAngle, &endAngle) != 6)
  181.     {
  182.       error("Illegal arc specification");
  183.       return;
  184.     }
  185.  
  186. /* we need the newpath since STROKE doesnt do a newpath */
  187.  
  188.   cmdout(NEWPATH);
  189.   numout((integer)hconvPS(xc));
  190.   numout((integer)vconvPS(yc));
  191.   numout((integer)convPS(xrad));
  192.   if (xrad != yrad)
  193.     numout((integer)convPS(yrad));
  194.   numout((integer)convDeg(startAngle));
  195.   numout((integer)convDeg(endAngle));
  196.  
  197.   if (xrad == yrad)             /* for arcs and circles */
  198.     cmdout("arc");
  199.   else
  200.     cmdout("ellipse");
  201.  
  202.   doShading();
  203. }                               /* end of arc */
  204.  
  205. void
  206. flushPath()
  207. {
  208.   register int i;
  209.  
  210.   if (pathLen < 2) 
  211.     {
  212.       error("Path less than 2 points - ignored");
  213.       return;
  214.     }
  215.   
  216. #ifdef DEBUG
  217.     if (dd(D_SPECIAL))
  218.         (void)fprintf(stderr,
  219. #ifdef SHORTINT
  220.             "flushpath(1): hh=%ld, vv=%ld, x=%ld, y=%ld, xPS=%ld, yPS=%ld\n",
  221. #else   /* ~SHORTINT */
  222.             "flushpath(1): hh=%d, vv=%d, x=%d, y=%d, xPS=%d, yPS=%d\n",
  223. #endif  /* ~SHORTINT */
  224.                     hh, vv, xx[1], yy[1], hconvPS(xx[1]), vconvPS(yy[1]));
  225. #endif /* DEBUG */
  226.   cmdout(NEWPATH); /* to save the current point */
  227.   numout((integer)hconvPS(xx[1]));
  228.   numout((integer)vconvPS(yy[1]));
  229.   cmdout(MOVETO);
  230.   for (i=2; i < pathLen; i++) {
  231. #ifdef DEBUG
  232.     if (dd(D_SPECIAL))
  233.         (void)fprintf(stderr,
  234. #ifdef SHORTINT
  235.             "flushpath(%ld): hh=%ld, vv=%ld, x=%ld, y=%ld, xPS=%ld, yPS=%ld\n",
  236. #else   /* ~SHORTINT */
  237.             "flushpath(%d): hh=%d, vv=%d, x=%d, y=%d, xPS=%d, yPS=%d\n",
  238. #endif  /* ~SHORTINT */
  239.                     i, hh, vv, xx[i], yy[i], hconvPS(xx[i]), vconvPS(yy[i]));
  240. #endif /* DEBUG */
  241.     numout((integer)hconvPS(xx[i]));
  242.     numout((integer)vconvPS(yy[i]));
  243.     cmdout(LINETO);
  244.     }
  245.   if (xx[1] == xx[pathLen] && yy[1] == yy[pathLen])
  246.     cmdout(CLOSEPATH);
  247.   else {
  248.     numout((integer)hconvPS(xx[pathLen]));
  249.     numout((integer)vconvPS(yy[pathLen]));
  250.     cmdout(LINETO);
  251.   }
  252.   doShading();
  253.   pathLen = 0;
  254. }                               /* end of flushPath */
  255.  
  256. void
  257. flushDashed(cp, dotted)
  258.      char *cp;
  259.      int dotted;
  260. {
  261.   float inchesPerDash;
  262.  
  263.   if (sscanf(cp, " %f ", &inchesPerDash) != 1) 
  264.     {
  265.       error ("Illegal format for dotted/dashed line");
  266.       return;
  267.     }
  268.   
  269.   if (inchesPerDash <= 0.0)
  270.     {
  271.       error ("Length of dash/dot cannot be negative");
  272.       return;
  273.     }
  274.  
  275.   inchesPerDash = 1000 * inchesPerDash; /* to get milli-inches */
  276.   
  277.   cmdout("[");
  278.   if (dotted) {
  279.     numout((integer)penSize);
  280.     numout((integer)convPS((int)inchesPerDash) - penSize);
  281.   } else                                /* if dashed */
  282.     numout((integer)convPS((int)inchesPerDash));
  283.  
  284.   cmdout("]");
  285.   numout((integer)0);
  286.   cmdout("setdash");
  287.  
  288.   flushPath();
  289.  
  290.   cmdout("[] 0 setdash");
  291. }                               /* end of flushDashed */
  292.  
  293. void
  294. flushSpline()
  295. {                               /* as exact as psdit!!! */
  296.   register long i, dxi, dyi, dxi1, dyi1;
  297.  
  298.   if (pathLen < 2)
  299.     {
  300.       error("Spline less than two points - ignored");
  301.       return;
  302.     }
  303.   
  304.   cmdout(NEWPATH);      /* to save the current point */
  305.   numout((integer)hconvPS(xx[1]));
  306.   numout((integer)vconvPS(yy[1]));
  307.   cmdout(MOVETO);
  308.   numout((integer)convPS((xx[2]-xx[1])/2));
  309.   numout((integer)convPS((yy[2]-yy[1])/2));
  310.   cmdout(RLINETO);
  311.  
  312.   for (i=2; i < pathLen; i++)
  313.     {
  314.       dxi = convPS(xx[i] - xx[i-1]);
  315.       dyi = convPS(yy[i] - yy[i-1]);
  316.       dxi1 = convPS(xx[i+1] - xx[i]);
  317.       dyi1 = convPS(yy[i+1] - yy[i]);
  318.  
  319.       numout((integer)dxi/3);
  320.       numout((integer)dyi/3);
  321.       numout((integer)(3*dxi+dxi1)/6);
  322.       numout((integer)(3*dyi+dyi1)/6);
  323.       numout((integer)(dxi+dxi1)/2);
  324.       numout((integer)(dyi+dyi1)/2);
  325.       cmdout(RCURVETO);
  326.     }
  327.  
  328.   numout((integer)hconvPS(xx[pathLen]));
  329.   numout((integer)vconvPS(yy[pathLen]));
  330.   cmdout(LINETO);
  331.  
  332.   doShading();
  333.   pathLen = 0;
  334.          
  335. }                               /* end of flushSpline */
  336.  
  337. /* set shading level (used with  Fig 1.4-TFX). priol@irisa.fr, 89/04 */
  338. void
  339. SetShade(cp)
  340. char *cp;
  341. {
  342.         
  343.  if (strncmp(cp,"55",2) == 0){
  344.          shadetp = 0.25; shading = LIGHT_GRAY;
  345.  }
  346.   else if (strncmp(cp,"cc",2) == 0){
  347.           shadetp = 0.50; shading = MEDIUM_GRAY;
  348.   }
  349.    else if (strncmp(cp,"c0",2) == 0){
  350.            shadetp = 0.75; shading = DARK_GRAY;
  351.    }       
  352. }                               /* end of SetShade       */
  353.  
  354. void
  355. shadeLast()
  356. {
  357.   char tpout[20];
  358.   shading = MEDIUM_GRAY;
  359.   sprintf(tpout,"%1.2f setgray",shadetp); /* priol@irisa.fr */
  360.   cmdout(tpout);
  361. }                               /* end of shadeLast */
  362.  
  363. void
  364. whitenLast()
  365. {
  366.   shading = WHITE;
  367.   cmdout("1 setgray");
  368. }                               /* end of whitenLast */
  369.  
  370. void
  371. blackenLast()
  372. {
  373.   shading = BLACK;
  374.   cmdout("0 setgray");          /* actually this aint needed */
  375. }                               /* end of whitenLast */
  376.  
  377. static void
  378. doShading()
  379. {
  380.   if (shading) 
  381.     {
  382.       cmdout(FILL);
  383.       shading = NONE;
  384.       cmdout("0 setgray");      /* default of black */
  385.     }
  386.   else
  387.     cmdout(STROKE);
  388. }                               /* end of doShading */
  389.  
  390. static integer
  391. zPixRound(x, conv)      /* return rounded number of pixels */
  392.         register integer x;             /* in DVI units */
  393.         register integer conv;          /* conversion factor */
  394. {
  395.     return((integer)((x + (conv >> 1)) / conv));
  396. }
  397.  
  398. #endif /* TPIC */
  399.  
  400.